﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using YJKArchUtils.Utils;
using YJKRevitDimensionText.OneKeyPlanDim.Utility;

namespace YJKRevitDimensionText.OneKeyPlanDim.DimData
{
	public class DbRampByDoor : DbDimBase
	{
		public DbRampByDoor(FamilyInstance familyInstance)
		{
			this.m_familyInstance = familyInstance;
		}

		public Line BaseLineFarAwayDoor
		{
			get
			{
				this.AnalysisInfo();
				return this.m_BaseLineFarAwayDoor;
			}
		}

		public XYZ CenterPoint
		{
			get
			{
				if (!this.AnalysisInfo())
				{
					return XYZ.Zero;
				}
				return GeometryHelper.GeometricCenterOfPlanarFace(this.m_BasePlanarFace);
			}
		}

		public override bool CreateSizeDim(Autodesk.Revit.DB.Document doc)
		{
			if (!base.CreateSizeDim(doc))
			{
				return false;
			}
			if (!this.AnalysisInfo())
			{
				return false;
			}
			this.CreateSizeDimWithLengthDir();
			this.CreateSizeDimWithWidthDir();
			return true;
		}

		public override bool CreateLevelDim(Autodesk.Revit.DB.Document doc, out List<SingleLevelDimDataInfo> lstAnnotationSymbol)
		{
			if (!base.CreateLevelDim(doc, out lstAnnotationSymbol))
			{
				return false;
			}
			if (!this.AnalysisInfo())
			{
				return false;
			}
			XYZ slopeDir = this.GetSlopeDir();
			XYZ xyz = (this.m_BaseLineFarAwayDoor.GetEndPoint(0) + this.m_BaseLineFarAwayDoor.GetEndPoint(1)) / 2.0 - slopeDir * (Common.MMToFeet(1500.0) * (double)this.m_doc.ActiveView.Scale / 100.0);
			if (base.ComponentInSlopePlanarFace != null)
			{
				xyz = CommonInterface.PtInPlanarFaceInDir(xyz, base.ComponentInSlopePlanarFace, XYZ.BasisZ);
			}
			FamilyInstance familyInstance = new LevelDimData(this.m_doc)
			{
				PtDimLocation = xyz,
				DimVal = base.FloorLevelVal
			}.CreateLevelDim();
			AnnotationSymbol annotationSymbol = null;
			if (familyInstance != null)
			{
				annotationSymbol = (familyInstance as AnnotationSymbol);
			}
			if (annotationSymbol != null)
			{
				SingleLevelDimDataInfo singleLevelDimDataInfo = new SingleLevelDimDataInfo(annotationSymbol);
				if (base.ComponentInSlopePlanarFace != null)
				{
					singleLevelDimDataInfo.LevelVal = xyz.Z;
				}
				else
				{
					singleLevelDimDataInfo.LevelVal = base.dFloorLevelVal;
				}
				singleLevelDimDataInfo.LadderLineLength = this.m_BaseLineFarAwayDoor.Length;
				singleLevelDimDataInfo.DimDir = this.GetSlopeDir().CrossProduct(XYZ.BasisZ);
				singleLevelDimDataInfo.PtLocation = xyz;
				singleLevelDimDataInfo.bStepDownDim = false;
				singleLevelDimDataInfo.m_LstElementId.Add(this.m_familyInstance.Id);
				lstAnnotationSymbol.Add(singleLevelDimDataInfo);
			}
			return true;
		}

		public override bool CreateSlopeDim(Autodesk.Revit.DB.Document doc)
		{
			if (!base.CreateSlopeDim(doc))
			{
				return false;
			}
			if (!this.AnalysisInfo())
			{
				return false;
			}
			if (this.m_BaseLineFarAwayDoor == null || this.m_BaseLineWithDoor == null)
			{
				return false;
			}
			XYZ xyz = (this.m_BaseLineFarAwayDoor.GetEndPoint(0) + this.m_BaseLineFarAwayDoor.GetEndPoint(1)) / 2.0;
			XYZ xyz2 = (this.m_BaseLineWithDoor.GetEndPoint(0) + this.m_BaseLineWithDoor.GetEndPoint(1)) / 2.0;
			FamilyInstance familyInstance = new SlopeDimData(this.m_doc)
			{
				PtStart = xyz,
				SlopeDimDir = (xyz2 - xyz).Normalize(),
				DimVal = this.m_strSlopeValue
			}.CreateSlopeDim();
			if (familyInstance == null)
			{
				return false;
			}
			base.SetSlopeOcclusionArea(familyInstance);
			return true;
		}

		private bool CreateSizeDimWithLengthDir()
		{
			XYZ xyz = (this.m_BaseLineFarAwayDoor.GetEndPoint(0) + this.m_BaseLineFarAwayDoor.GetEndPoint(1)) / 2.0;
			XYZ xyz2 = ((this.m_BaseLineWithDoor.GetEndPoint(0) + this.m_BaseLineWithDoor.GetEndPoint(1)) / 2.0 - xyz).Normalize();
			Grid grid = null;
			DbAxial dbAxial = null;
			if (base.GetDbAxialWithDir(xyz2, out dbAxial))
			{
				double num = 0.0;
				grid = dbAxial.GetGridNearestXZY(this.m_BaseLineFarAwayDoor.GetEndPoint(0), ref num);
				double num2 = 0.0;
				Grid gridNearestXZY = dbAxial.GetGridNearestXZY(this.m_BaseLineFarAwayDoor.GetEndPoint(1), ref num2);
				if (Geometry.LessThan(num2, num))
				{
					grid = gridNearestXZY;
				}
			}
			DetailCurve detailCurveWithPoint = CommonInterface.GetDetailCurveWithPoint(this.m_doc, this.m_BaseLineFarAwayDoor.GetEndPoint(0), xyz2);
			DetailCurve detailCurveWithPoint2 = CommonInterface.GetDetailCurveWithPoint(this.m_doc, this.m_BaseLineFarAwayDoor.GetEndPoint(1), xyz2);
			ReferenceArray referenceArray = new ReferenceArray();
			if (detailCurveWithPoint != null)
			{
				Reference reference = new Reference(detailCurveWithPoint);
				referenceArray.Append(reference);
			}
			if (detailCurveWithPoint2 != null)
			{
				Reference reference = new Reference(detailCurveWithPoint2);
				referenceArray.Append(reference);
			}
			if (grid != null)
			{
				XYZ xyz3 = (grid.Curve as Line).Project(this.m_BaseLineFarAwayDoor.GetEndPoint(0)).XYZPoint;
				xyz3 = new XYZ(xyz3.X, xyz3.Y, this.m_BaseLineFarAwayDoor.GetEndPoint(0).Z);
				DetailCurve detailCurveWithPoint3 = CommonInterface.GetDetailCurveWithPoint(this.m_doc, xyz3, xyz2);
				if (detailCurveWithPoint3 != null)
				{
					Reference reference = new Reference(detailCurveWithPoint3);
					referenceArray.Append(reference);
				}
			}
			Line line = this.m_BaseLineFarAwayDoor.Clone() as Line;
			double dLength = Common.MMToFeet(600.0) * (double)(this.m_doc.ActiveView.Scale / 100);
			line = CommonInterface.NextDodgeLine(line, -xyz2, dLength);
			Dimension dimension = new SizeDimData(this.m_doc, line, referenceArray).CreateDim(true);
			if (dimension == null)
			{
				return false;
			}
			this.SetDimPosition(dimension, line, -xyz2);
			return true;
		}

		private void SetDimPosition(Dimension newDim, Line lineRef, XYZ dir)
		{
			List<CurveLoop> componentAndSizeAndSlopeOcclusionArea = OcclusionArea.GetInstance().GetComponentAndSizeAndSlopeOcclusionArea();
			List<CurveLoop> sizeDimCurveLoop = OcclusionArea.GetSizeDimCurveLoop(newDim);
			List<CurveLoop> list = new List<CurveLoop>();
			XYZ origin = lineRef.Origin;
			XYZ ptEnd = origin;
			for (int i = 0; i < 3; i++)
			{
				ptEnd = CommonInterface.GetNextPositionByOffset(i, Common.MMToFeet(300.0), origin, dir);
				list = CommonInterface.MoveLstCurve(sizeDimCurveLoop, origin, ptEnd);
				bool flag = false;
				using (List<CurveLoop>.Enumerator enumerator = list.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						if (CommonInterface.IsExistOcclusion(enumerator.Current, componentAndSizeAndSlopeOcclusionArea))
						{
							flag = true;
							break;
						}
					}
				}
				if (!flag)
				{
					break;
				}
				if (2 == i)
				{
					ptEnd = origin;
					break;
				}
			}
			OcclusionArea.GetInstance().m_lstSizeDimCvLoop.AddRange(list);
			CommonInterface.MoveElement(newDim, origin, ptEnd, this.m_doc);
		}

		private bool CreateSizeDimWithWidthDir()
		{
			XYZ xyz = (this.m_BaseLineFarAwayDoor.GetEndPoint(0) + this.m_BaseLineFarAwayDoor.GetEndPoint(1)) / 2.0;
			XYZ xyz2 = (this.m_BaseLineWithDoor.GetEndPoint(0) + this.m_BaseLineWithDoor.GetEndPoint(1)) / 2.0;
			XYZ xyz3 = (xyz2 - xyz).Normalize();
			Grid grid = null;
			DbAxial dbAxial = null;
			if (base.GetDbAxialWithDir(this.m_BaseLineFarAwayDoor.Direction, out dbAxial))
			{
				double num = 0.0;
				grid = dbAxial.GetGridNearestXZY(xyz, ref num);
				double num2 = 0.0;
				Grid gridNearestXZY = dbAxial.GetGridNearestXZY(xyz2, ref num2);
				if (Geometry.LessThan(num2, num))
				{
					grid = gridNearestXZY;
				}
			}
			XYZ dir = XYZ.BasisZ.CrossProduct(xyz3).Normalize();
			DetailCurve detailCurveWithPoint = CommonInterface.GetDetailCurveWithPoint(this.m_doc, xyz, dir);
			DetailCurve detailCurveWithPoint2 = CommonInterface.GetDetailCurveWithPoint(this.m_doc, xyz2, dir);
			ReferenceArray referenceArray = new ReferenceArray();
			if (detailCurveWithPoint != null)
			{
				Reference reference = new Reference(detailCurveWithPoint);
				referenceArray.Append(reference);
			}
			if (detailCurveWithPoint2 != null)
			{
				Reference reference = new Reference(detailCurveWithPoint2);
				referenceArray.Append(reference);
			}
			if (grid != null)
			{
				XYZ xyz4 = (grid.Curve as Line).Project(xyz).XYZPoint;
				xyz4 = new XYZ(xyz4.X, xyz4.Y, xyz.Z);
				DetailCurve detailCurveWithPoint3 = CommonInterface.GetDetailCurveWithPoint(this.m_doc, xyz4, dir);
				if (detailCurveWithPoint3 != null)
				{
					Reference reference = new Reference(detailCurveWithPoint3);
					referenceArray.Append(reference);
				}
			}
			Line line = Line.CreateBound(xyz2, xyz);
			double dLength = this.m_BaseLineFarAwayDoor.Length / 2.0 + Common.MMToFeet(600.0) * (double)(this.m_doc.ActiveView.Scale / 100);
			line = CommonInterface.NextDodgeLine(line, dir, dLength);
			Dimension dimension = new SizeDimData(this.m_doc, line, referenceArray).CreateDim(true);
			if (dimension == null)
			{
				return false;
			}
			this.SetDimPosition(dimension, line, dir);
			return true;
		}

		public bool AnalysisInfo()
		{
			if (!base.IsNeedAnalysisInfo())
			{
				return true;
			}
			try
			{
				List<PlanarFace> allPlanarFace = this.GetAllPlanarFace(this.m_familyInstance);
				this.CalBasePlanarFace(ref allPlanarFace);
				this.CalPlanarFaceWithDoor(allPlanarFace);
				this.CalUpLineWithDoor();
				if (!this.CalBaseLineFarAwayDoor())
				{
					return false;
				}
				this.CalSlopeValue();
				List<CurveLoop> list = new List<CurveLoop>();
				foreach (CurveLoop curveLoop in this.m_BasePlanarFace.GetEdgesAsCurveLoops())
				{
					CurveLoop xyplaneCurve = CommonInterface.GetXYPlaneCurve(curveLoop);
					list.Add(xyplaneCurve);
				}
				OcclusionArea.GetInstance().AddRampCurve(this.m_familyInstance.Id, list);
			}
			catch
			{
				return false;
			}
			return !(this.m_BaseLineFarAwayDoor == null);
		}

		private List<PlanarFace> GetAllPlanarFace(Element element)
		{
			List<PlanarFace> allPlanarFace = GeometryHelper.GetAllPlanarFace(element);
			for (int i = 0; i < allPlanarFace.Count; i++)
			{
				if (Geometry.LessThan(allPlanarFace[i].Area, 1.0))
				{
					allPlanarFace.RemoveAt(i);
					i--;
				}
			}
			return allPlanarFace;
		}

		private void CalBasePlanarFace(ref List<PlanarFace> lstPlanarFace)
		{
			foreach (PlanarFace planarFace in lstPlanarFace)
			{
				if (GeometryHelper.VectorParallelVector(planarFace.FaceNormal, XYZ.BasisZ))
				{
					this.m_BasePlanarFace = planarFace;
					break;
				}
			}
		}

		private void CalPlanarFaceWithDoor(List<PlanarFace> lstPlanarFace)
		{
			this.m_BaseLineWithDoor = null;
			foreach (PlanarFace planarFace in lstPlanarFace)
			{
				List<Curve> list = null;
				if (GeometryHelper.VectorVerticalVector(planarFace.FaceNormal, XYZ.BasisZ) && GeometryHelper.Is2PlanarFaceHasCommonEdge(planarFace, this.m_BasePlanarFace, out list) && GeometryHelper.LstCvLoop2LstCurve(planarFace.GetEdgesAsCurveLoops().ToList<CurveLoop>()).Count == 4 && list.Count == 1)
				{
					this.m_AffixedToDoorPlanarFace = planarFace;
					this.m_BaseLineWithDoor = (list[0] as Line);
					if (this.m_BaseLineWithDoor != null)
					{
						break;
					}
				}
			}
		}

		private void CalUpLineWithDoor()
		{
			if (this.m_BaseLineWithDoor == null)
			{
				return;
			}
			List<Curve> lstCv = GeometryHelper.LstCvLoop2LstCurve(this.m_AffixedToDoorPlanarFace.GetEdgesAsCurveLoops().ToList<CurveLoop>());
			List<Line> parallelLineInLstCv = GeometryHelper.GetParallelLineInLstCv(this.m_BaseLineWithDoor, lstCv);
			if (parallelLineInLstCv.Count == 1)
			{
				this.m_UpLineWithDoor = parallelLineInLstCv[0];
			}
		}

		private XYZ GetSlopeDir()
		{
			XYZ xyz = this.m_BaseLineFarAwayDoor.Direction.CrossProduct(XYZ.BasisZ).Normalize();
			XYZ xyz2 = this.m_BaseLineFarAwayDoor.Origin + Common.MMToFeet(100.0) * xyz;
			if (!Geometry.LessThan(this.m_BaseLineWithDoor.Distance(xyz2), this.m_BaseLineWithDoor.Distance(this.m_BaseLineFarAwayDoor.Origin)))
			{
				xyz = -xyz;
			}
			return xyz;
		}

		private bool CalBaseLineFarAwayDoor()
		{
			if (this.m_BaseLineWithDoor == null)
			{
				return false;
			}
			List<Curve> lstCv = GeometryHelper.LstCvLoop2LstCurve(this.m_BasePlanarFace.GetEdgesAsCurveLoops().ToList<CurveLoop>());
			List<Line> parallelLineInLstCv = GeometryHelper.GetParallelLineInLstCv(this.m_BaseLineWithDoor, lstCv);
			if (parallelLineInLstCv.Count != 1)
			{
				return false;
			}
			this.m_BaseLineFarAwayDoor = parallelLineInLstCv[0];
			return true;
		}

		private void CalSlopeValue()
		{
			if (this.m_UpLineWithDoor == null || this.m_BaseLineWithDoor == null || this.m_BaseLineFarAwayDoor == null)
			{
				return;
			}
			double num = GeometryHelper.Distance2ParallelLine(this.m_UpLineWithDoor, this.m_BaseLineWithDoor);
			if (Geometry.IsEqual(num, 0.0))
			{
				return;
			}
			double num2 = GeometryHelper.Distance2ParallelLine(this.m_BaseLineFarAwayDoor, this.m_BaseLineWithDoor) / num;
			int num3 = (int)num2;
			if (Geometry.IsEqual(num2, (double)num3))
			{
				this.m_strSlopeValue = num3.ToString();
			}
			else
			{
				this.m_strSlopeValue = num2.ToString("f2");
			}
			this.m_strSlopeValue = "1 : " + this.m_strSlopeValue;
		}

		private FamilyInstance m_familyInstance;

		private PlanarFace m_AffixedToDoorPlanarFace;

		private PlanarFace m_BasePlanarFace;

		private Line m_UpLineWithDoor;

		private Line m_BaseLineWithDoor;

		private Line m_BaseLineFarAwayDoor;

		private string m_strSlopeValue = string.Empty;
	}
}
